package ca.tatham.triplipse.views;

import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.widgets.Control;

import ca.tatham.triplipse.Activator;
import ca.tatham.triplipse.IRdfDocumentChangeListener;
import ca.tatham.triplipse.filter.IRdfFilterListener;
import ca.tatham.triplipse.filter.IRdfStatementFilter;

public abstract class RdfDocumentContentProvider implements
		IRdfDocumentChangeListener, IRdfFilterListener,
		IStructuredContentProvider, ILabelProviderListener {

	private Viewer m_viewer;
	private IRdfStatementFilter m_filter;

	protected abstract void filterChanged();

	/**
	 * By default, simply refresh the elements of the viewer. Implementations
	 * must override this method if they need to clear variables, set flags,
	 * etc, so that <code>#getElements()</code> is called
	 * 
	 * @see ca.tatham.triplipse.IRdfDocumentChangeListener#rdfChanged()
	 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
	 */
	public void rdfChanged() {
		refresh();
	}

	public final void inputChanged(Viewer newViewer, Object oldInput,
			@SuppressWarnings("unused")
			Object newInput) {
		if (oldInput == null) {
			Activator.getDefault().getRdfDocument().addRdfListener(this);
		}
		this.m_viewer = newViewer;
	}

	public final void setFilter(IRdfStatementFilter filter) {
		m_filter = filter;
		if (m_filter != null) {
			filterChanged();
		}
	}

	public final IRdfStatementFilter getFilter() {
		return m_filter;
	}

	public final boolean isFiltered() {
		return m_filter != null;
	}

	public void dispose() {
		// do nothing
	}

	protected Viewer getViewer() {
		return m_viewer;
	}

	public final void labelProviderChanged(@SuppressWarnings("unused")
	LabelProviderChangedEvent event) {
		refresh();
	}

	protected final void refresh() {
		getViewer().getControl().getDisplay().asyncExec(new Runnable() {
			public void run() {
				// This method runs inside an asyncExec. The widget may have
				// been destroyed by the time this is run. Check for this and do
				// nothing if so.
				Control ctrl = getViewer().getControl();
				if (ctrl == null || ctrl.isDisposed()) {
					return;
				}

				getViewer().refresh();
			}
		});
	}

}
